Skip to content

fix(interp): deftype fails at its own form with a locating error - #355

Merged
csm merged 5 commits into
csm:mainfrom
BuddhiLW:upstream/deftype-locating-error
Aug 30, 2026
Merged

fix(interp): deftype fails at its own form with a locating error#355
csm merged 5 commits into
csm:mainfrom
BuddhiLW:upstream/deftype-locating-error

Conversation

@BuddhiLW

Copy link
Copy Markdown
Contributor

deftype was a builtin wired to a nil stub, so (deftype T [x y]) took the
function-application path, evaluated its args, and died on the unbound symbol T
with "Unable to resolve symbol: T" — an error that names a symbol and points
nowhere near the real cause. deftype is genuinely unimplemented (it needs
mutable/volatile fields, set! over them, and array interop).

Made it a special form that returns "deftype is not implemented (defining T);
use defrecord where a map-backed type suffices" without evaluating its args, so
the failure lands on the deftype line and says what is actually missing.
Removed the unreachable builtin registration. defrecord and reify unaffected;
suite 431/431.

deftype was a builtin wired to a nil stub, so (deftype T [x y]) took the
function-application path, evaluated its args, and died on the unbound symbol T
with "Unable to resolve symbol: T" — an error that names a symbol and points
nowhere near the real cause. deftype is genuinely unimplemented (it needs
mutable/volatile fields, set! over them, and array interop).

Made it a special form that returns "deftype is not implemented (defining T);
use defrecord where a map-backed type suffices" without evaluating its args, so
the failure lands on the deftype line and says what is actually missing.
Removed the unreachable builtin registration. defrecord and reify unaffected;
suite 431/431.
@csm csm self-assigned this Aug 29, 2026
@csm
csm self-requested a review August 29, 2026 04:01
@csm
csm merged commit 35dd5d6 into csm:main Aug 30, 2026
2 checks passed
andrewdean pushed a commit to andrewdean/clojurust that referenced this pull request Sep 2, 2026
…ith tests

The merge of main into upstream/deftype resolved the conflict in
interp/special.rs by keeping BOTH sides of eval_deftype: a truncated copy of
the new one — its body cut off after the field-spec parse and an orphan
fragment of intern_type_symbol's body spliced in, referencing `globals` and
`ns` that do not exist there — followed by csm#355's old "not implemented" stub.
That is E0428 plus two E0425, so cljrs-runtime did not compile at all: both the
WASM build and Build/test/lint went red, the WASM job on the compile errors and
the lint job on rustfmt drift the same merge left behind.

Three things the merges silently reverted, restored:

1. eval_deftype's body. It registers the protocol impls with the mutable field
   names, builds the positional ->T constructor (routing to
   make-type-instance-mut when the type declares mutable fields) and interns
   the type symbol. The duplicate stub is gone.

2. defrecord's field parse, back onto the shared parse_field_specs rather than
   a second hand-rolled copy. parse_field_specs now reads the vector through
   `as_vector`, so a marker on the field vector itself — (defrecord R ^:marker
   [x]) — stays transparent for deftype as it already was for defrecord.

3. resolve_protocol_sym's three call sites (PR csm#354). The merges dropped all
   three back to lookup_in_ns(current_ns, "mp/IThing"), leaving the helper dead
   — which also fails `clippy -D warnings` — and cross-namespace protocol impls
   broken again with "mp/IThing is not a protocol".

Everything outside special.rs survived and is unchanged: TypeInstance.mutable,
the serialize fold, rt_assoc, the set! lowering declines, .-field dispatch and
the make-type-instance-mut builtin.

Nothing caught any of this, because nothing tested the behaviour — so:

- deftype_types.rs: the constructor, .-field, instance?, the absent map->T,
  fields in scope in a method body, multi-protocol dispatch, set! in both forms,
  instance independence, and mixed immutable/mutable fields.
- deftype_mutable_tiered.rs: its own binary so it can force eager IR lowering
  process-wide. Three of its four tests fail when the set!-on-a-local decline
  is removed ("IR interpreter: var not found user/n"), and the immutable
  control still passes — the tree-walking tests cannot discriminate there.
- qualified_protocol_impl.rs: all five impl sites across a namespace boundary,
  by alias and fully qualified, plus the same-ns control. Six of the seven fail
  when resolve_protocol_sym is neutered.

Docs: differences.md and TODO.md said deftype is not implemented; the crate
READMEs now carry TypeInstance.mutable, the shared deftype/defrecord helpers,
the .-field dispatch rule and the set! lowering decline.

Verified: cargo fmt --check, clippy --workspace -D warnings, cargo test
--workspace, the wasm32-unknown-unknown release build, and the AOT
clojure-test-suite (310 tests / 5543 assertions, 0 failures).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wdq2umKkdALhZbbGMxM8n1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants